package modelo;

import java.util.*;

import titiritero.*;
import vistas.VistaEscenario;

public class Escenario implements Posicionable, Iterable<Objeto>, Observado {
	
        private ArrayList<Objeto> objetos;
        private ArrayList<ObservadorDeEscenario> Observadores;
        private int altitud;
        private int longitud;
        private TanqueAlgo jugador = null;
        private Cuartel cuartel = null;

        public Escenario(int altitud, int longitud) {
        	this.objetos = new ArrayList<Objeto>();
        	this.altitud = altitud;
        	this.longitud = longitud;
        	this.Observadores = new ArrayList<ObservadorDeEscenario>();
        }
        
		public TanqueAlgo getAlgoTank() {
			return this.jugador;
		}
		
		public Cuartel getCuartel() {
			return this.cuartel;
		}

        public ArrayList<Objeto> getObjetos() {
        	return this.objetos;
        }

        public int getLongitud() {
        	return this.longitud;
        }

        public int getAltitud() {
        	return this.altitud;
        }
        
        public boolean contieneA(Objeto unObjeto) {
        	return (this.objetos.contains(unObjeto));
        }
        
        public boolean agregarJugador(TanqueAlgo jugador) {
        	this.jugador = jugador;
        	agregarObjeto(jugador);
        	return true;
        }
        
		public boolean agregarCuartel(Cuartel cuartel) {
			this.cuartel = cuartel;
        	agregarObjeto(cuartel);
        	return true;			
		}
		
        public boolean agregarObjeto(Objeto unObjeto) {
        	if (unObjeto.estaFueraDeLimites(this)) {
        		return false;
        	}
        	else {
        		for (Objeto o : this.objetos) {
        			if (unObjeto.solapadoCon(o)) {
        				return false;
        			}
        		}
        	}
        	
        	this.objetos.add(unObjeto);
        	this.notificarObjetoNuevo(unObjeto);
        	return true;
        }

        public boolean eliminarObjeto(Objeto objeto) {
            if (! this.objetos.remove(objeto)) {
            	return false;
            }
        	this.notificarObjetoEliminado(objeto);
            return true;
        }

        
        public boolean permiteMovimiento(ObjetoDinamico objeto) {
        	return (! objeto.estaFueraDeLimites(this));
        }
        
        public int cantidadObjetos() {
        	return this.objetos.size();
        }
        
        
        public void vivir() {
			@SuppressWarnings("unchecked")
			ArrayList<Objeto> copiaDeObjetos = (ArrayList<Objeto>) this.objetos.clone();
			
        	Iterator<Objeto> iterador = copiaDeObjetos.iterator();
        	while (iterador.hasNext()) {
        		Objeto objeto = iterador.next();
        		objeto.vivir();
        	}
        }
        
		@Override
		public Iterator<Objeto> iterator() {
			return this.objetos.iterator();
		}

		@Override
		public double getX() {
			return 0.0;
		}

		@Override
		public double getY() {
			return 0.0;
		}

		public Dibujable crearDibujable() {
			VistaEscenario vistaEscenario = new VistaEscenario();
			vistaEscenario.setPosicionable(this);			
			return vistaEscenario;
		}

		@Override
		public void notificarObjetoNuevo(Objeto unObjeto) {
			Iterator<ObservadorDeEscenario> iterador = this.Observadores.iterator();
			while(iterador.hasNext()) {
				ObservadorDeEscenario ANotificar = iterador.next();
				ANotificar.notificarObjetoNuevo(unObjeto);
			}
		}

		@Override
		public void notificarObjetoEliminado(Objeto unObjeto) {
			Iterator<ObservadorDeEscenario> iterador = this.Observadores.iterator();
			while(iterador.hasNext()) {
				ObservadorDeEscenario ANotificar = iterador.next();
				ANotificar.notificarObjetoEliminado(unObjeto);
			}
			
		}

		@Override
		public void agregarObservador(ObservadorDeEscenario unObservador) {
			this.Observadores.add(unObservador);
			
		}
		
		public void agregarProyectil(Proyectil proyectil) {
		    @SuppressWarnings("unchecked")
		    
		    ArrayList<Objeto> copiaDeObjetos = (ArrayList<Objeto>) this.objetos.clone();
		    Iterator<Objeto> iterador = copiaDeObjetos.iterator();
		    
		    while (iterador.hasNext()) {
		        Objeto objeto = iterador.next();
		        if( proyectil.getFigura().estaSolapadoCon(objeto.getFigura()) ) {
		            objeto.chocarConProyectil(proyectil);
		            return;
		            }
		        }
		    
		    this.agregarObjeto(proyectil);
        }

}
